#!/usr/bin/python
## UDP Scanning Script - Nicholas Albright Oct 2014
import logging, sys, os, time
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
from scapy.all import *
conf.verb=0

class Colors():
    color = {	
    "purple" : "\033[95m",
    "yellow" : "\033[93m",
    "norm" : "\033[0m",
    "vuln" : "\033[1;91mVULNERABLE\033[0m",
    "secure" : "\033[1;92mSECURE\033[0m",
    "closed" : "\033[1;96mCLOSED\033[0m"
    }

def scan(ipdata):
    count = 0
    for line in ipdata:
    	line = line.strip('\n')
    	print Colors.color["purple"] + str(line) + Colors.color["norm"] + ": ", 
    	print "[ %sNTP%s (Mode 6) -" % (Colors.color["yellow"], Colors.color["norm"]),
    	mode6, mode7 = ntpscan(line)
    	print Colors.color[mode6],
    	print ":: (Mode 7) -", Colors.color[mode7],
    	print "] || [ %sDNS%s -"% (Colors.color["yellow"], Colors.color["norm"]),  
    	dnsresp = dnsscan(line)
    	print Colors.color[dnsresp],
    	print "] || [ %sSSDP%s -" %(Colors.color["yellow"], Colors.color["norm"]), 
    	ssdpresp = ssdpscan(line)
    	print Colors.color[ssdpresp],
    	print "] || [ %sSNMP%s -" %(Colors.color["yellow"], Colors.color["norm"]), 
    	snmpresp = snmpscan(line)
    	print Colors.color[snmpresp],
    	print "]"
    	count += 1
    	if count >= 15:
    		time.sleep(5)  ## BSD OS's require a pause to let the network interfaces relax....take a break.
    		count = 0


def ntpscan(ipdata):
    try:
            packet=sr1(IP(dst=str(ipdata))/UDP(dport=123,sport=(random.randrange(20000,65000)))/Raw(load=str("\x16\x02\x00\x01")+ str("\00")*8),timeout=.5)
       	if len(packet) > 0:	
    		if "IP / ICMP" in str(packet.summary()):
    			readvar = ("closed")
    		else: 
    			readvar = ("vuln")
    except: 
    	 readvar = ("secure")
  
        try:	
           	packet=sr1(IP(dst=str(ipdata))/UDP(dport=123,sport=(random.randrange(20000,65000)))/Raw(load=str("\x17\x00\x03\x2a")+ str("\00")*4),timeout=.5)
       	if len(packet) > 0:	
    		if "IP / ICMP" in str(packet.summary()):
    			monlist = ("closed")
    		else: 
    			monlist = ("vuln")
    except: 
    	monlist = ("secure")
       
    return (readvar, monlist)

def dnsscan(ipdata):
    try:	
            packet=sr1(IP(dst=str(ipdata))/UDP(dport=53,sport=(random.randrange(20000,65000)))/DNS(rd=1,qd=DNSQR(qname="t.co")),verbose=0,timeout=1)
       	resp = packet[DNS].summary()
    	if len(resp) > 10:
    		if "IP / ICMP" in str(packet.summary()):
    			return("closed")
    		else:
    			return("vuln")
    	else:
    		return("secure")
    except:
     	return("secure")

def ssdpscan(ipdata):
    try:
    	types = ["ssdp:all", "upnp:rootdevice", "urn:schemas-upnp-org:device:InternetGatewayDevice:1"]
    	for eachtype in types:
    		udpsocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    		udpsocket.settimeout(1)
    		searchstr = "M-SEARCH * HTTP/1.1\nHost: 239.255.255.0:1900\nST:%s\nMan: \"ssdp:discover\"\nMX:1\r\n\r\n" % ( eachtype )
    		udpsocket.sendto(str(searchstr), (ipdata, 1900))
    		packet = response = ""
    		returndata = []
    		try:
    			partialresponse = udpsocket.recv(1024)
    			response = partialresponse
    			if len(response) > 1:
    				packet += response	
    		except:
    			pass
    	udpsocket.close()
    	if len(packet) > 0:
    		if "IP / ICMP" in str(packet.summary()):
    			return("closed")
    		else:
    			return("vuln")
    	else:
    		return("secure")
    except:
    	return("secure")
    
def snmpscan(ipdata):
    try:
    	packet = packet=sr1(IP(dst=str(ipdata))/UDP(dport=161,sport=(random.randrange(20000,65000)))/SNMP(community="public",PDU=SNMPget(varbindlist=[SNMPvarbind(oid=ASN1_OID("1.3.6.1.2.1.1.1.0"))])), timeout=1)
    	if len(packet) > 0:
    		if "IP / ICMP" in str(packet.summary()):
    			return("closed")
    		else:
    			return("vuln")
    	else:
    		return("secure")
    except:
    	return ("secure")


if __name__ == "__main__":
    if os.geteuid() != 0:
    	print "Root privs are required to interact with the interface. Please run with sudo."
    	sys.exit()
    if (len(sys.argv)) > 1:
       	lines = sys.argv[1:]
    else:
       	var = raw_input("Please enter the filename: ")
        	f = open(var,'r')    
       	lines = f.readlines()
       	f.close()
    scan(lines)	
